from django.shortcuts import render
from rest_framework.viewsets import ModelViewSet

from .serializer import *
from .modelsutils import *
from django.conf import settings
from .utils import *
from rest_framework import viewsets
from django.core.mail import send_mail
from rest_framework.views import APIView
from .paging import PagePagination
from django.contrib.auth.models import User
from rest_framework.response import Response
from django.contrib.auth import authenticate
from rest_framework.authtoken.models import Token  # 导入DRF为我们提供的Token模型


class UserSerializerTest(serializers.ModelSerializer):
    class Meta:
        model = User
        # fields = '__all__'
        # 设置包含哪些字段
        fields = ('username', 'email', 'last_login', 'is_superuser')


class TestView(ModelViewSet):
    # 认证
    # authentication_classes = []

    permission_classes = []

    queryset = User.objects.all()

    # 当视图继承 ModelViewSet 时，序列化类需要继承 ModelSerializer 才能发送 post 请求
    serializer_class = UserSerializerTest


class UserCreate(APIView):
    throttle_scope = 'anon'
    """
    用户注册视图
    """

    # 默认是全局进行权限限制的(检查用户是否登录)，所以这里需要放行
    # 绕过权限认证
    # 配置要使用的认证类，可以用如下方式配置（类属性方式）
    # authentication_classes = ()
    # 也可以用如下方式配置（实例方法）
    def get_authenticators(self):
        return ()  # 返回一个空的元组，表示从全局认证方式中豁免

    # 配置要使用的权限为，可以使用类属性，也可以使用方法
    # permission_classes = ()
    def get_permissions(self):
        return ()  # 返回一个空的元组，表示从全局认证方式中豁免

    def post(self, request):
        username = request.data.get('username')
        password = request.data.get('password')
        email = request.data.get('email')
        if User.objects.filter(email=email):
            return Response(
                data={
                    'msg': '该邮箱已被注册，请更换新的邮箱！',
                }
            )
        if User.objects.filter(username=username):
            return Response(
                data={
                    'msg': '该账号名已被注册，请更换新的账号名！',
                }
            )
        user = User(
            email=email,
            username=username,
        )
        # 使用user.set_password()对密码编码，而不使用原始字符作为密码
        user.set_password(password)
        user.save()  # 保存User的实例
        # 保存User实例后，在Token模型（数据库表）中，也对应保存一个Token实例作为用户的token
        Token.objects.create(user=user)
        return Response(
            data={
                'msg': 'success',
            }
        )


class Index(APIView):
    throttle_scope = 'anon'

    # 默认是全局进行权限限制的(检查用户是否登录)，所以这里需要放行
    # 绕过权限认证
    # 配置要使用的认证类，可以用如下方式配置（类属性方式）
    # authentication_classes = ()
    # 也可以用如下方式配置（实例方法）
    def get_authenticators(self):
        return ()  # 返回一个空的元组，表示从全局认证方式中豁免

    # 对用户登录进行权限管理，使用这个API不须要是已认证过的，所以从全局权限限制中豁免
    # 可以使用类属性，也可以使用方法
    # permission_classes = ()
    def get_permissions(self):
        return ()

    def get(self, request):
        return render(request, 'index.html')


class LoginView(APIView):
    """
    用户登录视图
    """
    throttle_scope = 'anon'

    # 默认是全局进行权限限制的(检查用户是否登录)，所以这里需要放行
    # 绕过权限认证
    # 配置要使用的认证类，可以用如下方式配置（类属性方式）
    # authentication_classes = ()
    # 也可以用如下方式配置（实例方法）
    def get_authenticators(self):
        return ()  # 返回一个空的元组，表示从全局认证方式中豁免

    # 对用户登录进行权限管理，使用这个API不须要是已认证过的，所以从全局权限限制中豁免
    # 可以使用类属性，也可以使用方法
    # permission_classes = ()
    def get_permissions(self):
        return ()

    def post(self, request):
        username = request.data.get('username')
        password = request.data.get('password')
        # 查询用户的 is_active 是否为 1
        info = User_filter_is_active(username)
        if info == 1:
            # 对用户名和密码进行认证，如果认证成功，则返回这个用户的实例
            user = authenticate(username=username, password=password)
            if user:
                # 判断用户身份，普通用户返回 user，管理员返回 super
                identity = User_identity(username)
                # 认证成功，从Token表中返回该用户的token
                return Response(
                    data={
                        'role': identity,
                        'token': user.auth_token.key,
                    }
                )
            else:
                # 认证失败，则返回相关信息和状态码
                return Response(
                    data={
                        'error': '登录失败，请确认账号和密码是否正确',
                    },
                )
        else:
            return Response(
                data={
                    'error': info,
                }
            )


class DetailInfo(APIView):
    """
    get: 获取 某一账号名 的报安详细信息
    post: 提交 用户的报安信息 到数据库
    """
    throttle_scope = 'user'

    # 暂未用到
    # def get(self, request):
    #     nickname = request.data.get('nickname')
    #     # 根据 账号名 查找用户对象
    #     user = User.objects.filter(username=nickname).first()
    #     # 根据 用户对象 查询用户报安详细信息
    #     detail_info = Detail_info_filter_user(user)
    #     return Response(
    #         data={
    #             'msg': detail_info,
    #         }
    #     )

    def post(self, request):
        print('------------------')
        # print('token1:{}'.format(request.body))
        # print('token2:{}'.format(request.data))
        print('token2:{}'.format(request))
        print('token4:{}'.format(request.user))
        print('token5:{}'.format(request.auth))
        print('token6:{}'.format(request.META))
        print('token7:{}'.format(request.META['HTTP_COOKIE']))

        name = request.data.get('name')  # 用户姓名
        province = request.data.get('province')  # 所在省
        city = request.data.get('city')  # 所在市
        area = request.data.get('area')  # 所在区
        phone = request.data.get('phone')  # 手机号
        urname = request.data.get('urname')  # 紧急联系人姓名
        urphone = request.data.get('urphone')  # 紧急联系人手机号
        exectime = request.data.get('exectime')  # 自动报安时间
        username = request.user  # 用户昵称(唯一标识符)
        # account = request.data.get('account')  # 用户账号名
        # password = request.data.get('password')  # 用户密码
        print(f"===={name, province, city, area, phone, urname, urphone, exectime, str(username)}")

        # 根据 账号名 查找用户对象
        user = User.objects.filter(username=username)[0]

        # 存储用户的详细报安信息(如果已存在则为修改)
        Detail_info_create(name, province, city, area, phone, urname,
                           urphone, exectime, user, str(username))
        return Response(
            data={
                'msg': '信息成功录入',
            }
        )


class Days(APIView):
    """
    用户查询用户剩余提交次数
    """
    throttle_scope = 'user'

    def post(self, request):
        username = request.user
        days = Detail_info_filter_days(username)
        return Response(
            data={
                'days': days,
                'msg': '成功',
            }
        )


class ChkAccount(APIView):
    """
    通过用户 账号 查询是否存在报平安账号密码
    """

    throttle_scope = 'chk'

    def post(self, request):
        username = request.user
        info = Detail_info_filter_username_account(username)
        return Response(
            data={
                'exist': info,
            }
        )


class UserData(APIView):
    """
    post: 根据用户 昵称，获取用户报安的信息
    """
    throttle_scope = 'chk'

    def post(self, request):
        username = request.user
        data = Detail_info_filter_username_getData(username)
        if data:
            return Response(
                data={
                    'msg': data,
                }
            )
        else:
            return Response(
                data={
                    'error': '该用户不存在报安信息',
                }
            )


class TopUp(APIView):
    """
    post: 通过秘钥 添加用户的使用天数
    """
    throttle_scope = 'user'

    def post(self, request):
        username = request.user  # 用户账号
        cdk = request.data.get('cdk')  # 秘钥
        print(f"-----{cdk, username}")
        # 查询该 username 是否已经提交报安信息
        info0 = Detail_info_filter_username(username)
        if info0 == 0:
            return Response(
                data={
                    'error': '您尚未提交详细报安信息，暂时无法充值！',
                }
            )
        # 判断秘钥是否存在且有效,如果有效则将 vaild 设置为0
        info = InvCode_filter_cdk(cdk)
        print(f"info:{info}")
        if type(info) == int:
            # 给 username 充值秘钥的天数
            Detail_info_recharge_days(username, info)
            # 将充值信息写入 OrderList 表
            info2 = OrderList_create(username, cdk, info)
            if info2:
                return Response(
                    data={
                        'success': 'yes',
                        'capacity': info,
                    }
                )
            else:
                return Response(
                    data={
                        'error': '充值订单数据写入失败！',
                    }
                )

        else:
            return Response(
                data={
                    'error': info,
                }
            )


class BindAccount(APIView):
    """
    绑定用户 学号、身份证后六位
    """
    throttle_scope = 'user'

    def post(self, request):
        username = request.user
        account = request.data.get('account')
        password = request.data.get('password')
        info = accountConfirm(account, password)
        print(f"info:::{username, account, password, info}")
        # 如果 正确
        if info:
            # 将 用户登录 信息写入到 Detail_info 表中
            info1 = Detail_info_add_account_password(username, account, password)
            if info1 == 'success':
                return Response(
                    data={
                        'success': 'yes',
                    }
                )
            else:
                return Response(
                    data={
                        'error': info1,
                    }
                )
        else:
            return Response(
                data={
                    'error': '登录信息错误，请检查后绑定!',
                }
            )


class SendEmail(APIView):
    """
    通过邮箱给用户发送验证码，并将验证码写入 Email_Code 表中
    """
    throttle_scope = 'email'

    def post(self, request):
        sending = request.data.get('email')
        # 发验证码
        subject = '【平安小助手】 您正在绑定平安小助手，若非本人操作，请忽略。'
        inside = '验证码: '
        message = str(random.randint(100000, 999999))  # 随机生成6位数的验证码
        from_email = settings.DEFAULT_FROM_EMAIL
        try:
            send_mail(subject, inside + message, from_email, [sending])
        except BaseException:
            return Response(
                data={
                    'error': '发送失败，请检查邮箱是否正确!',
                }
            )
        # 记录存到数据库 [邮箱、验证码、时间戳]
        Email_Code_create(email=sending, code=message)
        return Response(
            data={
                'success': 'yes',
            }
        )


class ChkEmail(APIView):
    """
    检测用户的验证码是否正确
    """
    throttle_scope = 'user'

    def post(self, request):
        username = request.user
        email = request.data.get('email')
        code = request.data.get('code')
        # 判断邮箱是否在 Email_Code 表中存在
        info = Email_Code_filter_email(email=email)
        if info:
            # 筛选出Email_Code表中包含上面邮箱的所有记录，取时间戳最新的那条校验
            record = Email_Code_filter_email_order_by(email=email)
            # 获取之前发送给用户的验证码 与 用户注册提交的验证码  判断是否一致
            if int(record.code) == code:
                # 此时，邮箱验证通过-->把该注册的邮箱信息在Email_Code表里删掉
                Email_Code_filter_email_delete(email=email)
                # 修改 User 表中 该username 的邮箱为 该验证通过的邮箱
                User_filter_username_modify_email(username, email)
                # 修改 Detail_info 表中 该 username 的邮箱为 该验证通过的邮箱
                info = Detail_info_filter_username_modify_email(username, email)
                if info == '成功':
                    return Response(
                        data={
                            'success': 'yes',
                        }
                    )
                else:
                    return Response(
                        data={
                            'error': info,
                        }
                    )
            else:
                return Response(
                    data={
                        'error': '验证码错误',
                    }
                )
        else:
            return Response(
                data={
                    'error': '请先获取验证码，或者请勿在获取验证码后修改邮箱!',
                }
            )


class HavEmail(APIView):
    """
    返回用户注册时的邮箱，并返回用户是否已经绑定邮箱
    """
    throttle_scope = 'chk'

    def post(self, request):
        username = request.user
        # 查询该用户注册时的邮箱
        # print(f"username...{username}")
        email = User_filter_username_email(username)
        # 查询该用户的邮箱是否已经绑定，注意用户未填写详细报安的情况
        info = Detail_info_filter_username_email(username)
        return Response(
            data={
                'email': email,
                'valid': info,
            }
        )


class HavDetInfo(APIView):
    """
    查询 用户是否存在报平安信息
    """
    throttle_scope = 'chk'

    def post(self, request):
        username = request.user
        # 查询该用户是否存在报平安信息
        info = Detail_info_filter_username(username)
        if info:
            return Response(
                data={
                    'success': 'yes'
                }
            )
        else:
            return Response(
                data={
                    'success': 'no'
                }
            )


class HavConfigAll(APIView):
    """
    检查用户信息是否配置完整
    """
    throttle_scope = 'chk'

    def post(self, request):
        username = request.user
        haveaccount = Detail_info_filter_username_account(username)
        havemail = Detail_info_filter_username_email(username)
        info = Detail_info_filter_username(username)
        if info:
            if haveaccount == 'yes':
                if havemail == 'yes':
                    Detail_info_filter_modify_start(username, 1)
                    return Response(
                        data={
                            'miss': 'None'  # 啥也不缺
                        }
                    )
                return Response(
                    data={
                        'miss': 'email'  # 缺少email信息
                    }
                )
            return Response(
                data={
                    'miss': 'account'  # 缺少 报平安账号密码
                }
            )
        return Response(
            data={
                'miss': 'di'  # 缺少detailinfo表信息，没有提交报安信息
            }
        )


class StratAuto(APIView):
    """
    用户开启报平安功能，检查天数和信息是否完全，如果没问题，就开始自动报平安
    """
    throttle_scope = 'user'

    def post(self, request):
        username = request.user
        haveaccount = Detail_info_filter_username_account(username)
        havemail = Detail_info_filter_username_email(username)
        days = Detail_info_filter_days(username)

        if int(days) > 0:
            if haveaccount == 'yes':
                if havemail == 'yes':
                    Detail_info_filter_modify_start(username, 1)
                    return Response(
                        data={
                            'success': 'yes'
                        }
                    )
                return Response(
                    data={
                        'error': '未绑定邮箱，请点击验证邮箱进行绑定！'
                    }
                )
            return Response(
                data={
                    'error': '未绑定报平安账号，请点击报平安账号进行绑定！'
                }
            )
        return Response(
            data={
                'error': '剩余天数不足，请充值！'
            }
        )
